package org.example.spring.repository.service.impl;

import lombok.extern.slf4j.Slf4j;
import org.example.spring.repository.service.IDepartmentService;
import org.example.spring.repository.service.IManyThreadsTransactionService;
import org.example.spring.utils.TransactionUtil;
import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionStatus;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 *
 *  保存每个线程的事务的提交状态，全部结束以后，根据信号量判断是否提交
 * LuoYu
 * 2022/12/19 16:48
 **/
@Service
@Slf4j
public class StatusListTransactionServiceImpl implements IManyThreadsTransactionService {

    @Resource
    private IDepartmentService departmentService;

    @Override
    public void exec() {

        int size = 5;
        CountDownLatch count = new CountDownLatch(size);
        AtomicBoolean single = new AtomicBoolean(false);
        List<TransactionStatus> statusList = Collections.synchronizedList(new ArrayList<>());
        for (int i=1; i<=size; i++) {
           boolean hasThrow = i % 3 == 0;
            //boolean hasThrow = false;
            departmentService.saveStatusAsyncTransactionCreate(String.valueOf(i),hasThrow,count,single,statusList);
        }
        PlatformTransactionManager transactionManager = TransactionUtil.getTransactionManager();

        try {
            // 等待执行完毕
            count.await();
            boolean b = single.get();
            if(b) {
                log.warn("发生异常，全部回滚");
                statusList.forEach(transactionManager::rollback);
            } else {
                log.info("执行成功，全部提交");
                statusList.forEach(transactionManager::commit);
            }
        } catch (InterruptedException e) {
            log.error("主线程发生异常，执行回滚",e);
            statusList.forEach(transactionManager::rollback);
            e.printStackTrace();
        }


    }
}
